Completed
Push — master ( e88c19...17669b )
by Rain
03:00
created

ko.bindingHandlers.popover.init   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
nop 2

1 Function

Rating   Name   Duplication   Size   Complexity  
A 0 3 1
1
2
import window from 'window';
3
import _ from '_';
4
import $ from '$';
5
import Opentip from 'Opentip';
6
import Pikaday from 'pikaday';
7
8
import {SaveSettingsStep, Magics} from 'Common/Enums';
9
10
const
11
	ko = window.ko,
12
	$win = $(window),
13
	fDisposalTooltipHelper = (element) => {
14
		ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
15
			if (element && element.__opentip)
16
			{
17
				element.__opentip.deactivate();
18
			}
19
		});
20
	};
21
22
ko.bindingHandlers.updateWidth = {
23
	init: (element, fValueAccessor) => {
24
		const
25
			$el = $(element),
26
			fValue = fValueAccessor(),
27
			fInit = () => {
28
				fValue($el.width());
29
				window.setTimeout(() => {
30
					fValue($el.width());
31
				}, Magics.Time500ms);
32
			};
33
34
		$win.on('resize', fInit);
35
		fInit();
36
37
		ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
38
			$win.off('resize', fInit);
39
		});
40
	}
41
};
42
43
ko.bindingHandlers.editor = {
44
	init: (element, fValueAccessor) => {
45
46
		let editor = null;
47
48
		const
49
			fValue = fValueAccessor(),
50
			HtmlEditor = require('Common/HtmlEditor').default,
51
			fUpdateEditorValue = () => {
52
				if (fValue && fValue.__editor)
53
				{
54
					fValue.__editor.setHtmlOrPlain(fValue());
55
				}
56
			},
57
			fUpdateKoValue = () => {
58
				if (fValue && fValue.__editor)
59
				{
60
					fValue(fValue.__editor.getDataWithHtmlMark());
61
				}
62
			},
63
			fOnReady = () => {
64
				fValue.__editor = editor;
65
				fUpdateEditorValue();
66
			};
67
68
		if (ko.isObservable(fValue) && HtmlEditor)
69
		{
70
			editor = new HtmlEditor(element, fUpdateKoValue, fOnReady, fUpdateKoValue);
71
72
			fValue.__fetchEditorValue = fUpdateKoValue;
73
74
			fValue.subscribe(fUpdateEditorValue);
75
76
//			ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
77
//			});
78
		}
79
	}
80
};
81
82
ko.bindingHandlers.json = {
83
	init: (element, fValueAccessor) => {
84
		$(element).text(window.JSON.stringify(ko.unwrap(fValueAccessor())));
85
	},
86
	update: (element, fValueAccessor) => {
87
		$(element).text(window.JSON.stringify(ko.unwrap(fValueAccessor())));
88
	}
89
};
90
91
ko.bindingHandlers.scrollerShadows = {
92
	init: (element) => {
93
94
		const
95
			limit = 8,
96
			$el = $(element),
97
			cont = $el.find('[data-scroller-shadows-content]')[0] || null,
98
			fFunc = _.throttle(() => {
99
				$el
100
					.toggleClass('scroller-shadow-top', limit < cont.scrollTop)
101
					.toggleClass('scroller-shadow-bottom', cont.scrollTop + limit < cont.scrollHeight - cont.clientHeight);
102
			}, 100);
103
104
		if (cont)
105
		{
106
			$(cont).on('scroll resize', fFunc);
107
			$win.on('resize', fFunc);
108
109
			ko.utils.domNodeDisposal.addDisposeCallback(cont, () => {
110
				$(cont).off();
111
				$win.off('resize', fFunc);
112
			});
113
		}
114
	}
115
};
116
117
ko.bindingHandlers.pikaday = {
118
	init: (element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext) => {
119
120
		ko.bindingHandlers.textInput.init(element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext);
121
122
		if (Pikaday)
123
		{
124
			element.__pikaday = new Pikaday({
125
				field: element
126
			});
127
		}
128
	}
129
};
130
131
ko.bindingHandlers.visibleAnimated = {
132
	init: (element, fValueAccessor) => {
133
		const $el = $(element);
134
		$el.addClass('rl-animated-visible');
135
		if (ko.unwrap(fValueAccessor())) {
136
			$el.how();
137
		} else {
138
			$el.hide();
139
		}
140
	},
141
	update: (element, fValueAccessor) => {
142
		const $el = $(element);
143
		if (ko.unwrap(fValueAccessor())) {
144
			$el.addClass('rl-animated-hidden').show();
145
			_.delay(() => {
146
				$el.removeClass('rl-animated-hidden');
147
			}, 10);
148
		} else {
149
			$el.hide().removeClass('rl-animated-hidden');
150
		}
151
	}
152
};
153
154
ko.bindingHandlers.tooltip = {
155
	init: (element, fValueAccessor) => {
156
157
		const
158
			$el = $(element),
159
			fValue = fValueAccessor(),
160
			isMobile = 'on' === ($el.data('tooltip-mobile') || 'off'),
161
			Globals = require('Common/Globals');
162
163
		if (!Globals.bMobileDevice || isMobile)
164
		{
165
			const sValue = !ko.isObservable(fValue) && _.isFunction(fValue) ? fValue() : ko.unwrap(fValue);
166
167
			element.__opentip = new Opentip(element, {
168
				'style': 'rainloopTip',
169
				'element': element,
170
				'tipJoint': $el.data('tooltip-join') || 'bottom'
171
			});
172
173
			Globals.dropdownVisibility.subscribe((v) => {
174
				if (v) {
175
					element.__opentip.hide();
176
				}
177
			});
178
179
			if ('' === sValue)
180
			{
181
				element.__opentip.hide();
182
				element.__opentip.deactivate();
183
				element.__opentip.setContent('');
184
			}
185
			else
186
			{
187
				element.__opentip.activate();
188
			}
189
190
			if ('on' === ($el.data('tooltip-i18n') || 'on'))
191
			{
192
				const Translator = require('Common/Translator');
193
194
				element.__opentip.setContent(Translator.i18n(sValue));
195
196
				Translator.trigger.subscribe(() => {
197
					element.__opentip.setContent(Translator.i18n(sValue));
198
				});
199
200
				Globals.dropdownVisibility.subscribe(() => {
201
					if (element && element.__opentip)
202
					{
203
						element.__opentip.setContent(Translator.i18n(sValue));
204
					}
205
				});
206
			}
207
			else
208
			{
209
				element.__opentip.setContent(sValue);
210
			}
211
		}
212
	},
213
	update: (element, fValueAccessor) => {
214
215
		const
216
			$el = $(element),
217
			fValue = fValueAccessor(),
218
			isMobile = 'on' === ($el.data('tooltip-mobile') || 'off'),
219
			Globals = require('Common/Globals');
220
221
		if ((!Globals.bMobileDevice || isMobile) && element.__opentip)
222
		{
223
			const sValue = !ko.isObservable(fValue) && _.isFunction(fValue) ? fValue() : ko.unwrap(fValue);
224
			if (sValue)
225
			{
226
				element.__opentip.setContent('on' === ($el.data('tooltip-i18n') || 'on') ?
227
					require('Common/Translator').i18n(sValue) : sValue);
228
229
				element.__opentip.activate();
230
			}
231
			else
232
			{
233
				element.__opentip.hide();
234
				element.__opentip.deactivate();
235
				element.__opentip.setContent('');
236
			}
237
		}
238
	}
239
};
240
241
ko.bindingHandlers.tooltipErrorTip = {
242
	init: function(element) {
243
244
		const $el = $(element);
245
246
		element.__opentip = new Opentip(element, {
247
			style: 'rainloopErrorTip',
248
			hideOn: 'mouseout click',
249
			element: element,
250
			tipJoint: $el.data('tooltip-join') || 'top'
251
		});
252
253
		element.__opentip.deactivate();
254
255
		$(window.document).on('click', () => {
256
			if (element && element.__opentip)
257
			{
258
				element.__opentip.hide();
259
			}
260
		});
261
262
		fDisposalTooltipHelper(element);
263
	},
264
	update: (element, fValueAccessor) => {
265
266
		const
267
			$el = $(element),
268
			fValue = fValueAccessor(),
269
			value = !ko.isObservable(fValue) && _.isFunction(fValue) ? fValue() : ko.unwrap(fValue),
270
			openTips = element.__opentip;
271
272
		if (openTips)
273
		{
274
			if ('' === value)
275
			{
276
				openTips.hide();
277
				openTips.deactivate();
278
				openTips.setContent('');
279
			}
280
			else
281
			{
282
				_.delay(() => {
283
					if ($el.is(':visible'))
284
					{
285
						openTips.setContent(value);
286
						openTips.activate();
287
						openTips.show();
288
					}
289
					else
290
					{
291
						openTips.hide();
292
						openTips.deactivate();
293
						openTips.setContent('');
294
					}
295
				}, Magics.Time100ms);
296
			}
297
		}
298
	}
299
};
300
301
ko.bindingHandlers.registrateBootstrapDropdown = {
302
	init: (element) => {
303
		const Globals = require('Common/Globals');
304
		if (Globals && Globals.data.aBootstrapDropdowns)
305
		{
306
			Globals.data.aBootstrapDropdowns.push($(element));
307
308
			$(element).click(() => {
309
				require('Common/Utils').detectDropdownVisibility();
310
			});
311
312
//			ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
313
//			});
314
		}
315
	}
316
};
317
318
ko.bindingHandlers.openDropdownTrigger = {
319
	update: (element, fValueAccessor) => {
320
		if (ko.unwrap(fValueAccessor()))
321
		{
322
			const $el = $(element);
323
			if (!$el.hasClass('open'))
324
			{
325
				$el.find('.dropdown-toggle').dropdown('toggle');
326
			}
327
328
			$el.find('.dropdown-toggle').focus();
329
330
			require('Common/Utils').detectDropdownVisibility();
331
			fValueAccessor()(false);
332
		}
333
	}
334
};
335
336
ko.bindingHandlers.dropdownCloser = {
337
	init: (element) => {
338
		$(element).closest('.dropdown').on('click', '.e-item', () => {
339
			$(element).dropdown('toggle');
340
		});
341
	}
342
};
343
344
ko.bindingHandlers.popover = {
345
	init: function(element, fValueAccessor) {
346
		$(element).popover(ko.unwrap(fValueAccessor()));
347
348
		ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
349
			$(element).popover('destroy');
350
		});
351
	}
352
};
353
354
ko.bindingHandlers.csstext = {};
355
ko.bindingHandlers.csstext.init = ko.bindingHandlers.csstext.update = (element, fValueAccessor) => {
356
	if (element && element.styleSheet && 'undefined' !== typeof element.styleSheet.cssText)
357
	{
358
		element.styleSheet.cssText = ko.unwrap(fValueAccessor());
359
	}
360
	else
361
	{
362
		$(element).text(ko.unwrap(fValueAccessor()));
363
	}
364
};
365
366
ko.bindingHandlers.resizecrop = {
367
	init: (element) => {
368
		$(element).addClass('resizecrop').resizecrop({
369
			'width': '100',
370
			'height': '100',
371
			'wrapperCSS': {
372
				'border-radius': '10px'
373
			}
374
		});
375
	},
376
	update: (element, fValueAccessor) => {
377
		fValueAccessor()();
378
		$(element).resizecrop({
379
			'width': '100',
380
			'height': '100'
381
		});
382
	}
383
};
384
385
ko.bindingHandlers.onEnter = {
386
	init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
387
		$(element).on('keypress.koOnEnter', (event) => {
388
			if (event && 13 === window.parseInt(event.keyCode, 10))
389
			{
390
				$(element).trigger('change');
391
				fValueAccessor().call(viewModel);
392
			}
393
		});
394
395
		ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
396
			$(element).off('keypress.koOnEnter');
397
		});
398
	}
399
};
400
401
ko.bindingHandlers.onSpace = {
402
	init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
403
		$(element).on('keyup.koOnSpace', (event) => {
404
			if (event && 32 === window.parseInt(event.keyCode, 10))
405
			{
406
				fValueAccessor().call(viewModel, event);
407
			}
408
		});
409
410
		ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
411
			$(element).off('keyup.koOnSpace');
412
		});
413
	}
414
};
415
416
ko.bindingHandlers.onTab = {
417
	init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
418
		$(element).on('keydown.koOnTab', (event) => {
419
			if (event && 9 === window.parseInt(event.keyCode, 10))
420
			{
421
				return fValueAccessor().call(viewModel, !!event.shiftKey);
422
			}
423
			return true;
424
		});
425
426
		ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
427
			$(element).off('keydown.koOnTab');
428
		});
429
	}
430
};
431
432
ko.bindingHandlers.onEsc = {
433
	init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
434
		$(element).on('keypress.koOnEsc', (event) => {
435
			if (event && 27 === window.parseInt(event.keyCode, 10))
436
			{
437
				$(element).trigger('change');
438
				fValueAccessor().call(viewModel);
439
			}
440
		});
441
442
		ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
443
			$(element).off('keypress.koOnEsc');
444
		});
445
	}
446
};
447
448
ko.bindingHandlers.clickOnTrue = {
449
	update: (element, fValueAccessor) => {
450
		if (ko.unwrap(fValueAccessor()))
451
		{
452
			$(element).click();
453
		}
454
	}
455
};
456
457
ko.bindingHandlers.modal = {
458
	init: (element, fValueAccessor) => {
459
460
		const
461
			Globals = require('Common/Globals'),
462
			Utils = require('Common/Utils');
463
464
		$(element)
465
			.toggleClass('fade', !Globals.bMobileDevice)
466
			.modal({
467
				'keyboard': false,
468
				'show': ko.unwrap(fValueAccessor())
469
			})
470
			.on('shown.koModal', Utils.windowResizeCallback)
471
			.find('.close').on('click.koModal', () => {
472
				fValueAccessor()(false);
473
			});
474
475
		ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
476
			$(element)
477
				.off('shown.koModal')
478
				.find('.close')
479
				.off('click.koModal');
480
		});
481
	},
482
	update: (element, fValueAccessor) => {
483
484
		const Globals = require('Common/Globals');
485
486
		$(element).modal(ko.unwrap(fValueAccessor()) ? 'show' : 'hide');
487
488
		if (Globals.$html.hasClass('rl-anim'))
489
		{
490
			Globals.$html.addClass('rl-modal-animation');
491
			_.delay(() => {
492
				Globals.$html.removeClass('rl-modal-animation');
493
			}, Magics.Time500ms);
494
		}
495
496
	}
497
};
498
499
ko.bindingHandlers.moment = {
500
	init: (element, fValueAccessor) => {
501
		require('Common/Momentor').momentToNode(
502
			$(element).addClass('moment').data('moment-time', ko.unwrap(fValueAccessor()))
503
		);
504
	},
505
	update: (element, fValueAccessor) => {
506
		require('Common/Momentor').momentToNode(
507
			$(element).data('moment-time', ko.unwrap(fValueAccessor()))
508
		);
509
	}
510
};
511
512
ko.bindingHandlers.i18nInit = {
513
	init: (element) => {
514
		require('Common/Translator').i18nToNodes(element);
515
	}
516
};
517
518
ko.bindingHandlers.translatorInit = {
519
	init: (element) => {
520
		require('Common/Translator').i18nToNodes(element);
521
	}
522
};
523
524
ko.bindingHandlers.i18nUpdate = {
525
	update: (element, fValueAccessor) => {
526
		ko.unwrap(fValueAccessor());
527
		require('Common/Translator').i18nToNodes(element);
528
	}
529
};
530
531
ko.bindingHandlers.link = {
532
	update: function(element, fValueAccessor) {
533
		$(element).attr('href', ko.unwrap(fValueAccessor()));
534
	}
535
};
536
537
ko.bindingHandlers.title = {
538
	update: function(element, fValueAccessor) {
539
		$(element).attr('title', ko.unwrap(fValueAccessor()));
540
	}
541
};
542
543
ko.bindingHandlers.textF = {
544
	init: function(element, fValueAccessor) {
545
		$(element).text(ko.unwrap(fValueAccessor()));
546
	}
547
};
548
549
ko.bindingHandlers.initDom = {
550
	init: function(element, fValueAccessor) {
551
		fValueAccessor()(element);
552
	}
553
};
554
555
ko.bindingHandlers.initFixedTrigger = {
556
	init: (element, fValueAccessor) => {
557
		const
558
			values = ko.unwrap(fValueAccessor()),
559
			$el = $(element),
560
			top = values[1] || 0;
561
562
		let $container = $(values[0] || null);
563
		$container = $container[0] ? $container : null;
564
		if ($container)
565
		{
566
			$win.resize(() => {
567
				const offset = $container.offset();
568
				if (offset && offset.top)
569
				{
570
					$el.css('top', offset.top + top);
571
				}
572
			});
573
		}
574
	}
575
};
576
577
ko.bindingHandlers.initResizeTrigger = {
578
	init: (element, fValueAccessor) => {
579
		const values = ko.unwrap(fValueAccessor());
580
		$(element).css({
581
			'height': values[1],
582
			'min-height': values[1]
583
		});
584
	},
585
	update: (oElement, fValueAccessor) => {
586
587
		const
588
			Utils = require('Common/Utils'),
589
			Globals = require('Common/Globals'),
590
			values = ko.unwrap(fValueAccessor());
591
592
		let
593
			value = Utils.pInt(values[1]),
594
			size = 0,
595
			offset = $(oElement).offset().top;
596
597
		if (0 < offset)
598
		{
599
			offset += Utils.pInt(values[2]);
600
			size = Globals.$win.height() - offset;
601
602
			if (value < size)
603
			{
604
				value = size;
605
			}
606
607
			$(oElement).css({
608
				'height': value,
609
				'min-height': value
610
			});
611
		}
612
	}
613
};
614
615
ko.bindingHandlers.appendDom = {
616
	update: (element, fValueAccessor) => {
617
		$(element).hide().empty().append(ko.unwrap(fValueAccessor())).show();
618
	}
619
};
620
621
ko.bindingHandlers.draggable = {
622
	init: (element, fValueAccessor, fAllBindingsAccessor) => {
623
624
		const
625
			Globals = require('Common/Globals'),
626
			Utils = require('Common/Utils');
627
628
		if (!Globals.bMobileDevice)
629
		{
630
			const
631
				triggerZone = 100,
632
				scrollSpeed = 3,
633
				fAllValueFunc = fAllBindingsAccessor(),
634
				droppableSelector = fAllValueFunc && fAllValueFunc.droppableSelector ? fAllValueFunc.droppableSelector : '',
635
				conf = {
636
					distance: 20,
637
					handle: '.dragHandle',
638
					cursorAt: {top: 22, left: 3},
639
					refreshPositions: true,
640
					scroll: true
641
				};
642
643
			if (droppableSelector)
644
			{
645
				conf.drag = (event) => {
646
647
					$(droppableSelector).each(function() {
648
						const
649
							$this = $(this), // eslint-disable-line no-invalid-this
650
							offset = $this.offset(),
651
							bottomPos = offset.top + $this.height();
652
653
						window.clearInterval($this.data('timerScroll'));
654
						$this.data('timerScroll', false);
655
656
						if (event.pageX >= offset.left && event.pageX <= offset.left + $this.width())
657
						{
658
							if (event.pageY >= bottomPos - triggerZone && event.pageY <= bottomPos)
659
							{
660
								const moveUp = () => {
661
									$this.scrollTop($this.scrollTop() + scrollSpeed);
662
									Utils.windowResize();
663
								};
664
665
								$this.data('timerScroll', window.setInterval(moveUp, 10));
666
								moveUp();
667
							}
668
669
							if (event.pageY >= offset.top && event.pageY <= offset.top + triggerZone)
670
							{
671
								const moveDown = () => {
672
									$this.scrollTop($this.scrollTop() - scrollSpeed);
673
									Utils.windowResize();
674
								};
675
676
								$this.data('timerScroll', window.setInterval(moveDown, 10));
677
								moveDown();
678
							}
679
						}
680
					});
681
				};
682
683
				conf.stop = () => {
684
					$(droppableSelector).each(function() {
685
						const $this = $(this); // eslint-disable-line no-invalid-this
686
						window.clearInterval($this.data('timerScroll'));
687
						$this.data('timerScroll', false);
688
					});
689
				};
690
			}
691
692
			conf.helper = (event) => fValueAccessor()(event && event.target ? ko.dataFor(event.target) : null);
693
694
			$(element).draggable(conf).on('mousedown.koDraggable', () => {
695
				Utils.removeInFocus();
696
			});
697
698
			ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
699
				$(element)
700
					.off('mousedown.koDraggable')
701
					.draggable('destroy');
702
			});
703
		}
704
	}
705
};
706
707
ko.bindingHandlers.droppable = {
708
	init: (element, fValueAccessor, fAllBindingsAccessor) => {
709
		const Globals = require('Common/Globals');
710
		if (!Globals.bMobileDevice)
711
		{
712
			const
713
				fValueFunc = fValueAccessor(),
714
				fAllValueFunc = fAllBindingsAccessor(),
715
				fOverCallback = fAllValueFunc && fAllValueFunc.droppableOver ? fAllValueFunc.droppableOver : null,
716
				fOutCallback = fAllValueFunc && fAllValueFunc.droppableOut ? fAllValueFunc.droppableOut : null,
717
				conf = {
718
					tolerance: 'pointer',
719
					hoverClass: 'droppableHover'
720
				};
721
722
			if (fValueFunc)
723
			{
724
				conf.drop = (event, ui) => {
725
					fValueFunc(event, ui);
726
				};
727
728
				if (fOverCallback)
729
				{
730
					conf.over = (event, ui) => {
731
						fOverCallback(event, ui);
732
					};
733
				}
734
735
				if (fOutCallback)
736
				{
737
					conf.out = (event, ui) => {
738
						fOutCallback(event, ui);
739
					};
740
				}
741
742
				$(element).droppable(conf);
743
744
				ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
745
					$(element).droppable('destroy');
746
				});
747
			}
748
		}
749
	}
750
};
751
752
ko.bindingHandlers.nano = {
753
	init: (element) => {
754
755
		const
756
			Globals = require('Common/Globals'),
757
			Settings = require('Storage/Settings');
758
759
		if (!Globals.bDisableNanoScroll && !Settings.appSettingsGet('useNativeScrollbars'))
760
		{
761
			$(element)
762
				.addClass('nano')
763
				.nanoScroller({
764
					iOSNativeScrolling: false,
765
					preventPageScrolling: true
766
				});
767
		}
768
	}
769
};
770
771
ko.bindingHandlers.saveTrigger = {
772
	init: (element) => {
773
774
		const $el = $(element);
775
776
		$el.data('save-trigger-type', $el.is('input[type=text],input[type=email],input[type=password],select,textarea') ? 'input' : 'custom');
777
778
		if ('custom' === $el.data('save-trigger-type'))
779
		{
780
			$el.append(
781
				'&nbsp;&nbsp;<i class="icon-spinner animated"></i><i class="icon-remove error"></i><i class="icon-ok success"></i>'
782
			).addClass('settings-saved-trigger');
783
		}
784
		else
785
		{
786
			$el.addClass('settings-saved-trigger-input');
787
		}
788
	},
789
	update: (element, fValueAccessor) => {
790
		const
791
			value = ko.unwrap(fValueAccessor()),
792
			$el = $(element);
793
794
		if ('custom' === $el.data('save-trigger-type'))
795
		{
796
			switch (value.toString())
797
			{
798
				case '1':
799
					$el
800
						.find('.animated,.error').hide().removeClass('visible')
801
						.end()
802
						.find('.success').show().addClass('visible');
803
					break;
804
				case '0':
805
					$el
806
						.find('.animated,.success').hide().removeClass('visible')
807
						.end()
808
						.find('.error').show().addClass('visible');
809
					break;
810
				case '-2':
811
					$el
812
						.find('.error,.success').hide().removeClass('visible')
813
						.end()
814
						.find('.animated').show().addClass('visible');
815
					break;
816
				default:
817
					$el
818
						.find('.animated').hide()
819
						.end()
820
						.find('.error,.success').removeClass('visible');
821
					break;
822
			}
823
		}
824
		else
825
		{
826
			switch (value.toString())
827
			{
828
				case '1':
829
					$el.addClass('success').removeClass('error');
830
					break;
831
				case '0':
832
					$el.addClass('error').removeClass('success');
833
					break;
834
				case '-2':
835
					break;
836
				default:
837
					$el.removeClass('error success');
838
					break;
839
			}
840
		}
841
	}
842
};
843
844
ko.bindingHandlers.emailsTags = {
845
	init: (element, fValueAccessor, fAllBindingsAccessor) => {
846
847
		const
848
			Utils = require('Common/Utils'),
849
			EmailModel = require('Model/Email').default,
850
851
			$el = $(element),
852
			fValue = fValueAccessor(),
853
			fAllBindings = fAllBindingsAccessor(),
854
			fAutoCompleteSource = fAllBindings.autoCompleteSource || null,
855
			fFocusCallback = (value) => {
856
				if (fValue && fValue.focused)
857
				{
858
					fValue.focused(!!value);
859
				}
860
			};
861
862
		$el.inputosaurus({
863
			parseOnBlur: true,
864
			allowDragAndDrop: true,
865
			focusCallback: fFocusCallback,
866
			inputDelimiters: [',', ';', '\n'],
867
			autoCompleteSource: fAutoCompleteSource,
868
//			elementHook: (el, item) => {
869
//				if (el && item)
870
//				{
871
//					el.addClass('pgp');
872
//				}
873
//			},
874
			parseHook: (input) => _.map(input, (inputValue) => {
875
				const value = Utils.trim(inputValue);
876
				if ('' !== value)
877
				{
878
					const email = new EmailModel();
879
					email.mailsoParse(value);
880
					return [email.toLine(false), email];
881
				}
882
				return [value, null];
883
884
			}),
885
			'change': (event) => {
886
				$el.data('EmailsTagsValue', event.target.value);
887
				fValue(event.target.value);
888
			}
889
		});
890
891
		if (fValue && fValue.focused && fValue.focused.subscribe)
892
		{
893
			fValue.focused.subscribe((value) => {
894
				$el.inputosaurus(value ? 'focus' : 'blur');
895
			});
896
		}
897
	},
898
	update: (element, fValueAccessor) => {
899
900
		const
901
			$oEl = $(element),
902
			fValue = fValueAccessor(),
903
			value = ko.unwrap(fValue);
904
905
		if ($oEl.data('EmailsTagsValue') !== value)
906
		{
907
			$oEl.val(value);
908
			$oEl.data('EmailsTagsValue', value);
909
			$oEl.inputosaurus('refresh');
910
		}
911
	}
912
};
913
914
ko.bindingHandlers.command = {
915
	init: (element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext) => {
916
		const
917
			jqElement = $(element),
918
			oCommand = fValueAccessor();
919
920
		if (!oCommand || !oCommand.enabled || !oCommand.canExecute)
921
		{
922
			throw new Error('You are not using command function');
923
		}
924
925
		jqElement.addClass('command');
926
		ko.bindingHandlers[jqElement.is('form') ? 'submit' : 'click']
927
			.init(element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext);
928
	},
929
	update: (element, fValueAccessor) => {
930
931
		const
932
			jqElement = $(element),
933
			command = fValueAccessor();
934
935
		let result = command.enabled();
936
937
		jqElement.toggleClass('command-not-enabled', !result);
938
939
		if (result)
940
		{
941
			result = command.canExecute();
942
			jqElement.toggleClass('command-can-not-be-execute', !result);
943
		}
944
945
		jqElement.toggleClass('command-disabled disable disabled', !result).toggleClass('no-disabled', !!result);
946
947
		if (jqElement.is('input') || jqElement.is('button'))
948
		{
949
			jqElement.prop('disabled', !result);
950
		}
951
	}
952
};
953
954
// extenders
955
956
ko.extenders.trimmer = (target) => {
957
	const
958
		Utils = require('Common/Utils'),
959
		result = ko.computed({
960
			read: target,
961
			write: (newValue) => {
962
				target(Utils.trim(newValue.toString()));
963
			}
964
		});
965
966
	result(target());
967
	return result;
968
};
969
970
ko.extenders.posInterer = (target, defaultVal) => {
971
	const
972
		Utils = require('Common/Utils'),
973
		result = ko.computed({
974
			read: target,
975
			write: (newValue) => {
976
				let val = Utils.pInt(newValue.toString(), defaultVal);
977
				if (0 >= val)
978
				{
979
					val = defaultVal;
980
				}
981
982
				if (val === target() && '' + val !== '' + newValue)
983
				{
984
					target(val + 1);
985
				}
986
987
				target(val);
988
			}
989
		});
990
991
	result(target());
992
	return result;
993
};
994
995
ko.extenders.limitedList = (target, limitedList) => {
996
	const
997
		Utils = require('Common/Utils'),
998
		result = ko.computed({
999
			read: target,
1000
			write: (newValue) => {
1001
1002
				const
1003
					currentValue = ko.unwrap(target),
1004
					list = ko.unwrap(limitedList);
1005
1006
				if (Utils.isNonEmptyArray(list))
1007
				{
1008
					if (-1 < Utils.inArray(newValue, list))
1009
					{
1010
						target(newValue);
1011
					}
1012
					else if (-1 < Utils.inArray(currentValue, list))
1013
					{
1014
						target(currentValue + ' ');
1015
						target(currentValue);
1016
					}
1017
					else
1018
					{
1019
						target(list[0] + ' ');
1020
						target(list[0]);
1021
					}
1022
				}
1023
				else
1024
				{
1025
					target('');
1026
				}
1027
			}
1028
		}).extend({notify: 'always'});
1029
1030
	result(target());
1031
1032
	if (!result.valueHasMutated)
1033
	{
1034
		result.valueHasMutated = () => {
1035
			target.valueHasMutated();
1036
		};
1037
	}
1038
1039
	return result;
1040
};
1041
1042
ko.extenders.reversible = (target) => {
1043
1044
	let value = target();
1045
1046
	target.commit = () => {
1047
		value = target();
1048
	};
1049
1050
	target.reverse = () => {
1051
		target(value);
1052
	};
1053
1054
	target.commitedValue = () => value;
1055
	return target;
1056
};
1057
1058
ko.extenders.toggleSubscribe = (target, options) => {
1059
	target.subscribe(options[1], options[0], 'beforeChange');
1060
	target.subscribe(options[2], options[0]);
1061
	return target;
1062
};
1063
1064
ko.extenders.toggleSubscribeProperty = (target, options) => {
1065
1066
	const prop = options[1];
1067
	if (prop)
1068
	{
1069
		target.subscribe((prev) => {
1070
			if (prev && prev[prop])
1071
			{
1072
				prev[prop](false);
1073
			}
1074
		}, options[0], 'beforeChange');
1075
1076
		target.subscribe((next) => {
1077
			if (next && next[prop])
1078
			{
1079
				next[prop](true);
1080
			}
1081
		}, options[0]);
1082
	}
1083
1084
	return target;
1085
};
1086
1087
ko.extenders.falseTimeout = (target, option) => {
1088
	target.iFalseTimeoutTimeout = 0;
1089
	target.subscribe((value) => {
1090
		if (value)
1091
		{
1092
			window.clearTimeout(target.iFalseTimeoutTimeout);
1093
			target.iFalseTimeoutTimeout = window.setTimeout(() => {
1094
				target(false);
1095
				target.iFalseTimeoutTimeout = 0;
1096
			}, require('Common/Utils').pInt(option));
1097
		}
1098
	});
1099
1100
	return target;
1101
};
1102
1103
ko.extenders.specialThrottle = (target, option) => {
1104
	target.iSpecialThrottleTimeoutValue = require('Common/Utils').pInt(option);
1105
	if (0 < target.iSpecialThrottleTimeoutValue)
1106
	{
1107
		target.iSpecialThrottleTimeout = 0;
1108
		target.valueForRead = ko.observable(!!target()).extend({throttle: 10});
1109
1110
		return ko.computed({
1111
			read: target.valueForRead,
1112
			write: (bValue) => {
1113
1114
				if (bValue)
1115
				{
1116
					target.valueForRead(bValue);
1117
				}
1118
				else
1119
				{
1120
					if (target.valueForRead())
1121
					{
1122
						window.clearTimeout(target.iSpecialThrottleTimeout);
1123
						target.iSpecialThrottleTimeout = window.setTimeout(() => {
1124
							target.valueForRead(false);
1125
							target.iSpecialThrottleTimeout = 0;
1126
						}, target.iSpecialThrottleTimeoutValue);
1127
					}
1128
					else
1129
					{
1130
						target.valueForRead(bValue);
1131
					}
1132
				}
1133
			}
1134
		});
1135
	}
1136
1137
	return target;
1138
};
1139
1140
ko.extenders.idleTrigger = (target) => {
1141
	target.trigger = ko.observable(SaveSettingsStep.Idle);
1142
	return target;
1143
};
1144
1145
// functions
1146
1147
ko.observable.fn.idleTrigger = function() {
1148
	return this.extend({'idleTrigger': true});
1149
};
1150
1151
ko.observable.fn.validateNone = function() {
1152
	this.hasError = ko.observable(false);
1153
	return this;
1154
};
1155
1156
ko.observable.fn.validateEmail = function() {
1157
1158
	this.hasError = ko.observable(false);
1159
1160
	this.subscribe((value) => {
1161
		this.hasError('' !== value && !(/^[^@\s]+@[^@\s]+$/.test(value)));
1162
	});
1163
1164
	this.valueHasMutated();
1165
	return this;
1166
};
1167
1168
ko.observable.fn.validateSimpleEmail = function() {
1169
1170
	this.hasError = ko.observable(false);
1171
1172
	this.subscribe((value) => {
1173
		this.hasError('' !== value && !(/^.+@.+$/.test(value)));
1174
	});
1175
1176
	this.valueHasMutated();
1177
	return this;
1178
};
1179
1180
ko.observable.fn.deleteAccessHelper = function() {
1181
	this.extend({falseTimeout: 3000}).extend({toggleSubscribe: [
1182
		null,
1183
		(prev) => {
1184
			if (prev && prev.deleteAccess)
1185
			{
1186
				prev.deleteAccess(false);
1187
			}
1188
		},
1189
		(next) => {
1190
			if (next && next.deleteAccess)
1191
			{
1192
				next.deleteAccess(true);
1193
			}
1194
		}
1195
	]});
1196
1197
	return this;
1198
};
1199
1200
ko.observable.fn.validateFunc = function(fFunc) {
1201
1202
	this.hasFuncError = ko.observable(false);
1203
1204
	if (_.isFunction(fFunc))
1205
	{
1206
		this.subscribe((value) => {
1207
			this.hasFuncError(!fFunc(value));
1208
		});
1209
1210
		this.valueHasMutated();
1211
	}
1212
1213
	return this;
1214
};
1215
1216
module.exports = ko;
1217